using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using PmSoft.Core.Domain.Auth;
using PmSoft.Web.Abstractions.ErrorCode;

namespace PmSoft.Web.Abstractions.Attributes;

/// <summary>
/// 自定义授权过滤器，用于限制访问的控制器或方法仅允许特定用户类型和租户类型的用户。
/// 通过检查 JWT Token 中的 "UserType" 和 "TenantType" 声明进行验证。
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class RestrictAccessAttribute : AuthorizeAttribute, IAuthorizationFilter
{
	private readonly string[]? _allowedUserTypes;
	private readonly string[]? _allowedTenantTypes;

	/// <summary>
	/// 初始化 <see cref="RestrictAccessAttribute"/> 的新实例。
	/// </summary>
	/// <param name="allowedUserTypes">允许的用户类型列表，为空表示不限制用户类型</param>
	/// <param name="allowedTenantTypes">允许的租户类型列表，为空表示不限制租户类型</param>
	public RestrictAccessAttribute(string[]? allowedUserTypes = null, string[]? allowedTenantTypes = null)
		: base()
	{
		_allowedUserTypes = allowedUserTypes;
		_allowedTenantTypes = allowedTenantTypes;
		AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme;
	}

	public void OnAuthorization(AuthorizationFilterContext context)
	{
		if (context == null)
		{
			throw new ArgumentNullException(nameof(context));
		}

		var user = context.HttpContext.User;

		if (user?.Identity?.IsAuthenticated != true)
		{
			context.Result = new JsonResult(ApiResult.Error("UNAUTHENTICATED","身份验证失败，请提供有效的凭据"))
			{
				StatusCode = ErrorCodeManager.GetError("UNAUTHENTICATED").HttpStatus
			};
			return;
		}

		// 获取当前用户
		var currentUser = context.HttpContext.Items["CurrentUser"] as IAuthedUser;
		if (currentUser == null)
		{
			context.Result = new JsonResult(ApiResult.Error("UNAUTHENTICATED", "当前用户未设置，授权失败"))
			{
				StatusCode = ErrorCodeManager.GetError("UNAUTHENTICATED").HttpStatus
			};
			return;
		}

		// 如果设置了用户类型限制，则进行验证
		if (_allowedUserTypes?.Length > 0)
		{
			if (string.IsNullOrEmpty(currentUser.UserType) || !_allowedUserTypes.Contains(currentUser.UserType))
			{

				context.Result = new JsonResult(ApiResult.Error("FORBIDDEN", "当前用户类型不能访问该资源"))
				{
					StatusCode = ErrorCodeManager.GetError("FORBIDDEN").HttpStatus
				};
				return;
			}
		}

		// 如果设置了租户类型限制，则进行验证
		if (_allowedTenantTypes?.Length > 0)
		{
			if (string.IsNullOrEmpty(currentUser.TenantType) || !_allowedTenantTypes.Contains(currentUser.TenantType))
			{
				context.Result = new JsonResult(ApiResult.Error("FORBIDDEN", "当前租户类型不能访问该资源"))
				{
					StatusCode = ErrorCodeManager.GetError("FORBIDDEN").HttpStatus
				};
				return;
			}
		}
	}
}